Option Explicit

' ==================================================
' 数组排序
' ==================================================
' 对数组类型的数据进行升序排序
'
' @param arr 数组
Public Sub sortAscArray(ByRef arr As Variant)
    Dim minIdx As Integer
    Dim maxIdx As Integer
    minIdx = LBound(arr)
    maxIdx = UBound(arr)
    ' 如果是空数组，则退出处理
    If maxIdx - minIdx + 1 = 0 Then
        Exit Sub
    End If

    doSortAscArray arr, minIdx, maxIdx
End Sub

' 辅助实现
' 对数组类型的数据进行升序排序
Private Sub doSortAscArray(ByRef arr As Variant, ByVal left As Long, ByVal right As Long)
    Dim l As Long
    Dim r As Long
    Dim pivot As Integer

    l = left
    r = right

    pivot = arr(r)

    While l < r
        While l < r And arr(l) <= pivot
            l = l + 1
        Wend
        If l < r Then
            arr(r) = arr(l)
            r = r - 1
        End If

        While l < r And arr(r) >= pivot
            r = r - 1
        Wend
        If l < r Then
            arr(l) = arr(r)
            l = l + 1
        End If
    Wend

    arr(r) = pivot

    If left < (r - 1) Then
        doSortAscArray arr, left, r - 1
    End If

    If (r + 1) < right Then
        doSortAscArray arr, r + 1, right
    End If
End Sub

' 对数组类型的数据进行降序排序
'
' @param arr 数组
Public Sub sortDescArray(ByRef arr As Variant)
    Dim minIdx As Integer
    Dim maxIdx As Integer
    minIdx = LBound(arr)
    maxIdx = UBound(arr)
    ' 如果是空数组，则退出处理
    If maxIdx - minIdx + 1 = 0 Then
        Exit Sub
    End If

    doSortDescArray arr, minIdx, maxIdx
End Sub

' 辅助实现
' 对数组类型的数据进行降序排序
Private Sub doSortDescArray(ByRef arr As Variant, ByVal left As Long, ByVal right As Long)
    Dim l As Long
    Dim r As Long
    Dim pivot As Integer

    l = left
    r = right

    pivot = arr(r)

    While l < r
        While l < r And arr(l) >= pivot
            l = l + 1
        Wend
        If l < r Then
            arr(r) = arr(l)
            r = r - 1
        End If

        While l < r And arr(r) <= pivot
            r = r - 1
        Wend
        If l < r Then
            arr(l) = arr(r)
            l = l + 1
        End If
    Wend

    arr(r) = pivot

    If left < (r - 1) Then
        doSortDescArray arr, left, r - 1
    End If

    If (r + 1) < right Then
        doSortDescArray arr, r + 1, right
    End If
End Sub

' ==================================================
' IObjArrayRef<PrimitivePair> Key2 排序
' ==================================================

' 对 `IObjArrayRef<PrimitivePair>` 类型的数据进行排序，排序时按照 key 的数据进行升序排序
'
' @param plist `IObjArrayRef<PrimitivePair>` 型的待排序数据
Public Sub sortAscPrimitivePairByKey2(ByRef plist As IObjArrayRef)
    ' 如果是空数组，则退出处理
    If plist.Count = 0 Then
        Exit Sub
    End If

    doSortAscPrimitivePairByKey2 plist, 0, plist.MaxIndex
End Sub

' 辅助实现
' 对 `IObjArrayRef<PrimitivePair>` 类型的数据进行排序，排序时按照 key 的数据进行升序排序
Private Sub doSortAscPrimitivePairByKey2(ByRef plist As IObjArrayRef, ByVal left As Long, ByVal right As Long)
    Dim l As Long
    Dim r As Long
    Dim rbackup As PrimitivePair
    Dim pivot As Integer

    l = left
    r = right

    With plist ' -- 在这里加速
        Set rbackup = .Item(r)
        pivot = rbackup.Key2

        While l < r
            While l < r And .Item(l).Key2 <= pivot
                l = l + 1
            Wend
            If l < r Then
                .setVal r, .Item(l)
                r = r - 1
            End If

            While l < r And .Item(r).Key2 >= pivot
                r = r - 1
            Wend
            If l < r Then
                .setVal l, .Item(r)
                l = l + 1
            End If
        Wend

        .setVal r, rbackup
    End With

    If left < (r - 1) Then
        doSortAscPrimitivePairByKey2 plist, left, r - 1
    End If

    If (r + 1) < right Then
        doSortAscPrimitivePairByKey2 plist, r + 1, right
    End If
End Sub

' 对 `IObjArrayRef<PrimitivePair>` 类型的数据进行排序，排序时按照 key 的数据进行降序序排序
'
' @param plist `IObjArrayRef<PrimitivePair>` 型的待排序数据
Public Sub sortDescPrimitivePairByKey2(ByRef plist As IObjArrayRef)
    ' 如果是空数组，则退出处理
    If plist.Count = 0 Then
        Exit Sub
    End If

    doSsortDescPrimitivePairByKey2 plist, 0, plist.MaxIndex
End Sub

' 辅助实现
' 对 `IObjArrayRef<PrimitivePair>` 类型的数据进行排序，排序时按照 key 的数据进行降序排序
Private Sub doSsortDescPrimitivePairByKey2(ByRef plist As IObjArrayRef, ByVal left As Long, ByVal right As Long)
    Dim l As Long
    Dim r As Long
    Dim rbackup As PrimitivePair
    Dim pivot As Integer

    l = left
    r = right

    With plist ' -- 在这里加速
        Set rbackup = .Item(r)
        pivot = rbackup.Key2

        While l < r
            While l < r And .Item(l).Key2 >= pivot
                l = l + 1
            Wend
            If l < r Then
                .setVal r, .Item(l)
                r = r - 1
            End If

            While l < r And .Item(r).Key2 <= pivot
                r = r - 1
            Wend
            If l < r Then
                .setVal l, .Item(r)
                l = l + 1
            End If
        Wend

        .setVal r, rbackup
    End With

    If left < (r - 1) Then
        doSsortDescPrimitivePairByKey2 plist, left, r - 1
    End If

    If (r + 1) < right Then
        doSsortDescPrimitivePairByKey2 plist, r + 1, right
    End If
End Sub